unit UFrameFieldList;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls, UPlatformDB, ComCtrls, ToolWin, CheckLst, ExtCtrls, DB,
  UVonConfig, UFrameConditionField, ImgList;

type
  TFrameFieldList = class(TFrame)
    tbSetting: TToolBar;
    btnTop: TToolButton;
    btnUp: TToolButton;
    btnDown: TToolButton;
    btnBottom: TToolButton;
    ToolButton1: TToolButton;
    btnDel: TToolButton;
    ToolButton3: TToolButton;
    btnSave: TToolButton;
    CheckListBox1: TCheckListBox;
    EFields: TComboBox;
    Panel1: TPanel;
    ETables: TComboBox;
    EStatistic: TComboBox;
    ImageList1: TImageList;
    procedure ETablesChange(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure CheckListBox1DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure btnTopClick(Sender: TObject);
    procedure btnUpClick(Sender: TObject);
    procedure btnDownClick(Sender: TObject);
    procedure btnBottomClick(Sender: TObject);
    procedure btnDelClick(Sender: TObject);
  private
    FOnLoadFields: TEventToLoadFields;
    FTables, FFields, FSelected: TVonNameValueData;
    FIsSelection: Boolean;
    procedure SetOnLoadFields(const Value: TEventToLoadFields);
    function GetOrdering: string;
    function GetSelection: string;
    procedure SetOrdering(const Value: string);
    procedure SetSelection(const Value: string);
    procedure SetIsSelection(const Value: Boolean);
    function GetGrouping: string;
    { Private declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SetTables(const ADataSet: TDataSet);
  published
    property IsSelection: Boolean read FIsSelection write SetIsSelection;
    property OnLoadFields: TEventToLoadFields read FOnLoadFields write SetOnLoadFields;
    property Selection: string read GetSelection write SetSelection;
    property Ordering: string read GetOrdering write SetOrdering;
    property Grouping: string read GetGrouping;
  end;

implementation

{$R *.dfm}

procedure TFrameFieldList.btnSaveClick(Sender: TObject);
begin
  FSelected.Add(FTables.Names[ETables.ItemIndex],
    FFields.Names[EFields.ItemIndex], TObject(EStatistic.ItemIndex));
  if FIsSelection and(EStatistic.ItemIndex > 0)then
    CheckListBox1.AddItem(EStatistic.Text + ' ' + ETables.Text + '.' + EFields.Text, nil)
  else CheckListBox1.AddItem(ETables.Text + '.' + EFields.Text, nil);
end;

procedure TFrameFieldList.CheckListBox1DrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  bmp: TBitmap;
begin
  if not FIsSelection then begin
    CheckListBox1.Canvas.TextRect(Rect, Rect.Left + 16, Rect.Top, CheckListBox1.Items[Index]);
    bmp:= TBitmap.Create;
    if CheckListBox1.Checked[Index] then ImageList1.GetBitmap(1, bmp)
    else ImageList1.GetBitmap(0, bmp);
    CheckListBox1.Canvas.Draw(Rect.Left, Rect.Top, bmp);
    bmp.Free;
  end else begin
    CheckListBox1.Checked[Index]:= False;
    CheckListBox1.Canvas.TextRect(Rect, Rect.Left, Rect.Top, CheckListBox1.Items[Index]);
  end;
end;

constructor TFrameFieldList.Create(AOwner: TComponent);
begin
  inherited;
  FTables:= TVonNameValueData.Create;
  FFields:= TVonNameValueData.Create;
  FSelected:= TVonNameValueData.Create;
end;

destructor TFrameFieldList.Destroy;
begin
  FSelected.Free;
  FFields.Free;
  FTables.Free;
  inherited;
end;

procedure TFrameFieldList.ETablesChange(Sender: TObject);
var
  I: Integer;
begin
  if Assigned(FOnLoadFields) then begin
    FOnLoadFields(Integer(FTables.Objects[ETables.ItemIndex - 1]), FFields);
    EFields.Items.Clear;
    for I := 0 to FFields.Count - 1 do
      EFields.Items.Add(FFields.Values[I]);
  end;
end;

function TFrameFieldList.GetGrouping: string;
var
  I: Integer;
  hasGroup: Boolean;
begin
  Result:= '';
  hasGroup:= False;
  for I := 0 to FSelected.Count - 1 do
    case Integer(FSelected.Objects[I]) of
    0: Result:= Result + ',' + FSelected.Names[I] + '.' + FSelected.Values[I];
    1, 2, 3: hasGroup:= True;
    end;
  if not hasGroup then Exit;
  if Result <> '' then
    Delete(Result, 1, 1);
end;

function TFrameFieldList.GetOrdering: string;
var
  I: Integer;
begin
  Result:= '';
  for I := 0 to FSelected.Count - 1 do
    if CheckListBox1.Checked[I] then
      Result:= Result + ',' + FSelected.Names[I] + '.' + FSelected.Values[I] + ' ASC'
    else Result:= Result + ',' + FSelected.Names[I] + '.' + FSelected.Values[I] + ' DESC';
  if Result <> '' then
    Delete(Result, 1, 1);
end;

function TFrameFieldList.GetSelection: string;
var
  I: Integer;
begin
  Result:= '';
  for I := 0 to FSelected.Count - 1 do
    case Integer(FSelected.Objects[I]) of
    0: Result:= Result + ',' + FSelected.Names[I] + '.' + FSelected.Values[I];
    1: Result:= Result + ',COUNT(' + FSelected.Names[I] + '.' + FSelected.Values[I] + ')';
    2: Result:= Result + ',SUM(' + FSelected.Names[I] + '.' + FSelected.Values[I] + ')';
    3: Result:= Result + ',AVG(' + FSelected.Names[I] + '.' + FSelected.Values[I] + ')';
    end;
  if Result <> '' then
    Delete(Result, 1, 1);
end;

procedure TFrameFieldList.SetIsSelection(const Value: Boolean);
begin
  FIsSelection := Value;
  EStatistic.Visible:= FIsSelection;
end;

procedure TFrameFieldList.SetOnLoadFields(const Value: TEventToLoadFields);
begin
  FOnLoadFields := Value;
end;

procedure TFrameFieldList.SetOrdering(const Value: string);
var
  I, mPos: Integer;
  S: string;
begin
  CheckListBox1.Items.Clear;
  FSelected.Clear;
  with TVonList.Create do try
    Delimiter:= ',';
    Text:= Value;
    for I := 0 to Count - 1 do begin
      S:= Strings[I];
      with TVonList.Create do try
        Delimiter:= ' ';
        Text:= S;
        mPos:= Pos('.', Strings[0]);
        if mPos > 0 then begin
          mPos:= FSelected.Add(Copy(Strings[0], 1, mPos - 1), Copy(Strings[0], mPos + 1, Length(Strings[0]) - mPos));
          ETables.ItemIndex:= FTables.IndexOfName(FSelected.Names[mPos]);
          ETablesChange(nil);
          EFields.ItemIndex:= FFields.IndexOfName(FSelected.Values[mPos]);
          CheckListBox1.Items.Add(ETables.Text + '.' + EFields.Text);
        end else begin
          mPos:= FSelected.Add('', Strings[0]);
          EFields.ItemIndex:= FFields.IndexOfName(FSelected.Values[mPos]);
          CheckListBox1.Items.Add(EFields.Text);
        end;
        CheckListBox1.Checked[mPos]:= Strings[1] = 'ASC';
      finally
        Free;
      end;
    end;
  finally
    Free;
  end;
end;

procedure TFrameFieldList.SetSelection(const Value: string);
var
  I, mPos, StatisticIdx: Integer;
  S: string;
begin
  CheckListBox1.Items.Clear;
  FSelected.Clear;
  // SUM(Num),A,B.sd
  with TVonList.Create do try
    Delimiter:= ',';
    Text:= Value;
    for I := 0 to Count - 1 do begin
      S:= Strings[I];
      if Copy(S, 1, 6) = 'COUNT(' then begin
        StatisticIdx:= 1;
        S:= Copy(S, 7, Length(S) - 7);
      end else if Copy(S, 1, 4) = 'SUM(' then begin
        StatisticIdx:= 2;
        S:= Copy(S, 5, Length(S) - 5);
      end else if Copy(S, 1, 4) = 'AVG(' then begin
        StatisticIdx:= 3;
        S:= Copy(S, 5, Length(S) - 5);
      end else StatisticIdx:= 0;
      mPos:= Pos('.', S);
      if mPos > 0 then begin
        mPos:= FSelected.Add(Copy(S, 1, mPos - 1), Copy(S, mPos + 1, Length(S) - mPos), TObject(StatisticIdx));
        ETables.ItemIndex:= FTables.IndexOfName(FSelected.Names[mPos]);
        ETablesChange(nil);
        EFields.ItemIndex:= FFields.IndexOfName(FSelected.Values[mPos]);
        if StatisticIdx > 0 then
          CheckListBox1.Items.Add(EStatistic.Items[StatisticIdx] + ' ' + ETables.Text + '.' + EFields.Text)
        else CheckListBox1.Items.Add(ETables.Text + '.' + EFields.Text);
      end else begin
        mPos:= FSelected.Add('', S, TObject(StatisticIdx));
        EFields.ItemIndex:= FFields.IndexOfName(FSelected.Values[mPos]);
        if StatisticIdx > 0 then
          CheckListBox1.Items.Add(EStatistic.Items[StatisticIdx] + ' ' + EFields.Text)
        else CheckListBox1.Items.Add(EFields.Text);
      end;
    end;
  finally
    Free;
  end;
end;

procedure TFrameFieldList.SetTables(const ADataSet: TDataSet);
var
  I: Integer;
begin
  FTables.Clear;
  ETables.Clear;
  if Assigned(ADataSet) then
    with ADataSet do begin
      First;
      while not EOF do begin
        FTables.Add(ADataSet.FieldByName('tbCode').AsString,
          ADataSet.FieldByName('tbName').AsString,
          TObject(ADataSet.FieldByName('ID').AsInteger));
        ETables.Items.Add(ADataSet.FieldByName('tbName').AsString);
        Next;
      end;
    end;
  ETables.ItemIndex:= 0;
end;

procedure TFrameFieldList.btnTopClick(Sender: TObject);
begin
  if CheckListBox1.ItemIndex < 0 then Exit;
  FSelected.Move(CheckListBox1.ItemIndex, 0);
  CheckListBox1.Items.Move(CheckListBox1.ItemIndex, 0);
  CheckListBox1.ItemIndex:= 0;
end;

procedure TFrameFieldList.btnUpClick(Sender: TObject);
begin
  if CheckListBox1.ItemIndex < 0 then Exit;
  FSelected.Move(CheckListBox1.ItemIndex, CheckListBox1.ItemIndex - 1);
  CheckListBox1.Items.Move(CheckListBox1.ItemIndex, CheckListBox1.ItemIndex - 1);
  CheckListBox1.ItemIndex:= CheckListBox1.ItemIndex - 1;
end;

procedure TFrameFieldList.btnBottomClick(Sender: TObject);
begin
  if CheckListBox1.ItemIndex < 0 then Exit;
  FSelected.Move(CheckListBox1.ItemIndex, FSelected.Count - 1);
  CheckListBox1.Items.Move(CheckListBox1.ItemIndex, FSelected.Count - 1);
  CheckListBox1.ItemIndex:= FSelected.Count - 1;
end;

procedure TFrameFieldList.btnDelClick(Sender: TObject);
begin
  if CheckListBox1.ItemIndex < 0 then Exit;
  FSelected.Delete(CheckListBox1.ItemIndex);
  CheckListBox1.DeleteSelected;
end;

procedure TFrameFieldList.btnDownClick(Sender: TObject);
begin
  if CheckListBox1.ItemIndex < 0 then Exit;
  FSelected.Move(CheckListBox1.ItemIndex, CheckListBox1.ItemIndex + 1);
  CheckListBox1.Items.Move(CheckListBox1.ItemIndex, CheckListBox1.ItemIndex + 1);
  CheckListBox1.ItemIndex:= CheckListBox1.ItemIndex + 1;
end;

end.
